from django.utils.decorators import method_decorator

from gis.common import track_logging
from gis.common.django_ext.decorators import validate_parameters
from gis.common.django_ext.views import BaseView, PaginationResponse
from gis.common.exceptions import BizException
from itpay.core.agency import transation_service, agency_service
from itpay.core.agency.const import AgencyType, AGENCY_SCORE_LEVEL
from itpay.core.agency.errors import (
    ERROR_NORMAL_AGENCY_CREATE,
    ERROR_AGREE_AGENCY_NOT_BELONG,
    ERROR_USER_PASSWORD_INCORRECT,
)
from itpay.server_agency.decorators import (
    require_login,
    check_user_vcode,
    check_user_white_ip,
)
from itpay.server_agency.view.agency.agency_forms import (
    LoginSchema,
    AddAgencySchema,
    UpdateAgencySchema,
    UpdateAgencyInfoSchema,
    ResetMyPasswordSchema,
    ComplainAgencySchema,
    AgencyStatsReportSchema,
    AgencyListSchema,
)
from itpay.server_agency.view.agency.helper import wrapper_agency_info, wrapper_name

_LOGGER = track_logging.getLogger(__name__)


class LoginView(BaseView):
    @method_decorator(validate_parameters(LoginSchema))
    def post(self, request, cleaned_data):
        user = agency_service.login(**cleaned_data)
        check_user_vcode(request, user)
        check_user_white_ip(request, user)
        return user


class LogoutView(BaseView):
    @method_decorator(require_login())
    def post(self, request):
        user_id = request.user_id
        agency_service.logout(user_id, request.token)
        agency_service.agency_go_off_work(user_id, remark="off work by logout")
        return dict(id=user_id)


class IMTokenView(BaseView):
    """
    获取IM Server Token
    """

    @method_decorator(require_login())
    def post(self, request):
        user_id = request.user_id
        agency = agency_service.get_agency_by_id(user_id)
        if not agency["im_id"]:
            agency_service.rpc_register_im(user_id)
        agency = agency_service.get_agency_by_id(user_id)
        return {"id": agency["im_id"], "token": agency["im_token"]}


class AgencyView(BaseView):
    @method_decorator(require_login())
    @method_decorator(validate_parameters(AgencyListSchema))
    def get(self, request, cleaned_data):
        user_id = request.user_id
        if cleaned_data.get("level"):
            cleaned_data["score"] = agency_service.calculate_score_by_level(
                cleaned_data["level"]
            )
            del cleaned_data["level"]

        total, agency = agency_service.list_agency(
            parent_id=user_id, return_many_to_many=True, **cleaned_data
        )
        return PaginationResponse(
            total,
            [
                wrapper_agency_info(
                    e, wrap_avatar=True, wrap_level=True, wrap_min_user_level=True
                )
                for e in agency
            ],
        )

    @method_decorator(require_login(check_vcode=True))
    @method_decorator(validate_parameters(AddAgencySchema))
    def post(self, request, cleaned_data):
        user = request.user
        if AgencyType(user["agency_type"]) == AgencyType.NORMAL_AGENCY:
            raise BizException(ERROR_NORMAL_AGENCY_CREATE)
        return agency_service.create_agency(
            **cleaned_data, agency_type=AgencyType.NORMAL_AGENCY, parent_id=user["id"]
        )


class RankConfView(BaseView):
    @method_decorator(require_login())
    def get(self, request):
        return AGENCY_SCORE_LEVEL


class AgencyDetailView(BaseView):
    @method_decorator(require_login())
    def get(self, request, agency_id):
        user_id = request.user_id

        if not agency_service.check_agency_parent(agency_id, user_id):
            raise BizException(ERROR_AGREE_AGENCY_NOT_BELONG)

        return wrapper_agency_info(
            agency_service.get_agency_by_id(agency_id, with_mch_info=True)
        )

    @method_decorator(validate_parameters(UpdateAgencySchema))
    @method_decorator(require_login(check_vcode=True))
    def put(self, request, agency_id, cleaned_data):
        user_id = request.user_id

        if not agency_service.check_agency_parent(agency_id, user_id):
            raise BizException(ERROR_AGREE_AGENCY_NOT_BELONG)

        agency_service.update_agency(agency_id, **cleaned_data)
        return dict(id=agency_id)


class AgencyInfoView(BaseView):
    @method_decorator(require_login())
    def get(self, request):
        agency_id = request.user_id
        agency = agency_service.get_agency_by_id(agency_id, with_mch_info=True)
        return wrapper_agency_info(
            agency,
            wrap_level=True,
            wrap_star=True,
            wrap_avatar=True,
            wrap_prologue=True,
            wrap_receipt_address_count=True,
        )

    @method_decorator(require_login())
    @method_decorator(validate_parameters(UpdateAgencyInfoSchema))
    def put(self, request, cleaned_data):
        agency_id = request.user_id
        agency_service.update_agency(agency_id, **cleaned_data)
        return dict(agency_id=request.user_id)


class GoToWork(BaseView):
    @method_decorator(require_login(check_white_ip=True))
    def post(self, request):
        user_id = request.user_id
        agency_service.agency_go_to_work(user_id)
        return dict(id=user_id)


class GoOffWork(BaseView):
    @method_decorator(require_login(check_white_ip=True))
    def post(self, request):
        user_id = request.user_id
        agency_service.agency_go_off_work(user_id, remark="off work by hand")
        return dict(id=user_id)


class ResetPasswordAgency(BaseView):
    @method_decorator(require_login(check_vcode=True))
    def post(self, request, agency_id):
        user_id = request.user_id
        if not agency_service.check_agency_parent(agency_id, user_id):
            raise BizException(ERROR_AGREE_AGENCY_NOT_BELONG)
        return agency_service.reset_password(agency_id)


class ResetMyPassword(BaseView):
    @method_decorator(require_login())
    @method_decorator(validate_parameters(ResetMyPasswordSchema))
    def post(self, request, cleaned_data):
        user = request.user
        user_name = user["user_name"]
        agency_id = user["id"]
        old_password = cleaned_data["old_password"]
        password = cleaned_data["password"]
        if not agency_service.verify_password(user_name, old_password):
            raise BizException(ERROR_USER_PASSWORD_INCORRECT)
        return agency_service.reset_password(agency_id, password=password)


class ComplaintView(BaseView):
    @method_decorator(require_login())
    @method_decorator(validate_parameters(ComplainAgencySchema))
    def get(self, request, cleaned_data):
        parent_id = request.user_id
        total, complain = agency_service.list_complaint_agency(
            **cleaned_data, parent_id=parent_id
        )
        return PaginationResponse(total, [wrapper_name(e) for e in complain])


class AgencyStatsReportView(BaseView):
    @method_decorator(require_login())
    @method_decorator(validate_parameters(AgencyStatsReportSchema))
    def get(self, request, cleaned_data):
        parent_ids = '["{}"]'.format(request.user_id)
        mch_type = "[]"
        total, resp_items = transation_service.get_agency_stats_report(
            **cleaned_data, parent_ids=parent_ids, mch_type=mch_type
        )
        return PaginationResponse(total, resp_items)
